﻿Imports System
Imports System.Collections.Generic

Namespace System.Workflow.ComponentModel
    Friend Class SequenceHelper
        ' Methods
        Public Shared Function Cancel(ByVal activity As CompositeActivity, ByVal executionContext As ActivityExecutionContext) As ActivityExecutionStatus
            Dim i As Integer = (activity.EnabledActivities.Count - 1)
            Do While (i >= 0)
                Dim activity2 As Activity = activity.EnabledActivities.Item(i)
                If (activity2.ExecutionStatus = ActivityExecutionStatus.Executing) Then
                    executionContext.CancelActivity(activity2)
                    Return activity.ExecutionStatus
                End If
                If ((activity2.ExecutionStatus = ActivityExecutionStatus.Canceling) OrElse (activity2.ExecutionStatus = ActivityExecutionStatus.Faulting)) Then
                    Return activity.ExecutionStatus
                End If
                If (activity2.ExecutionStatus = ActivityExecutionStatus.Closed) Then
                    activity.RemoveProperty(SequenceHelper.ActiveChildQualifiedNameProperty)
                    Return ActivityExecutionStatus.Closed
                End If
                i -= 1
            Loop
            Return ActivityExecutionStatus.Closed
        End Function

        Public Shared Function Execute(ByVal activity As CompositeActivity, ByVal executionContext As ActivityExecutionContext) As ActivityExecutionStatus
            If (activity.EnabledActivities.Count = 0) Then
                Return ActivityExecutionStatus.Closed
            End If
            activity.EnabledActivities.Item(0).RegisterForStatusChange(Activity.ClosedEvent, DirectCast(activity, IActivityEventListener([Of] ActivityExecutionStatusChangedEventArgs)))
            executionContext.ExecuteActivity(activity.EnabledActivities.Item(0))
            activity.SetValue(SequenceHelper.ActiveChildQualifiedNameProperty, activity.EnabledActivities.Item(0).QualifiedName)
            Return ActivityExecutionStatus.Executing
        End Function

        Public Shared Sub OnActivityChangeRemove(ByVal activity As CompositeActivity, ByVal executionContext As ActivityExecutionContext, ByVal removedActivity As Activity)
            Dim str As String = [TryCast](activity.GetValue(SequenceHelper.ActiveChildQualifiedNameProperty),String)
            If removedActivity.QualifiedName.Equals(str) Then
                activity.SetValue(SequenceHelper.ActiveChildRemovedProperty, True)
            End If
        End Sub

        Public Shared Sub OnEvent(ByVal activity As CompositeActivity, ByVal sender As Object, ByVal e As ActivityExecutionStatusChangedEventArgs)
            Dim executionContext As ActivityExecutionContext = [TryCast](sender,ActivityExecutionContext)
            e.Activity.UnregisterForStatusChange(Activity.ClosedEvent, DirectCast(activity, IActivityEventListener([Of] ActivityExecutionStatusChangedEventArgs)))
            If (((activity.ExecutionStatus = ActivityExecutionStatus.Canceling) OrElse (activity.ExecutionStatus = ActivityExecutionStatus.Faulting)) OrElse ((activity.ExecutionStatus = ActivityExecutionStatus.Executing) AndAlso Not SequenceHelper.TryScheduleNextChild(activity, executionContext))) Then
                activity.RemoveProperty(SequenceHelper.ActiveChildQualifiedNameProperty)
                executionContext.CloseActivity
            End If
        End Sub

        Public Shared Sub OnWorkflowChangesCompleted(ByVal activity As CompositeActivity, ByVal executionContext As ActivityExecutionContext)
            Dim str As String = [TryCast](activity.GetValue(SequenceHelper.ActiveChildQualifiedNameProperty),String)
            Dim flag As Boolean = CBool(activity.GetValue(SequenceHelper.ActiveChildRemovedProperty))
            If (((Not str Is Nothing) AndAlso flag) AndAlso (((activity.ExecutionStatus = ActivityExecutionStatus.Canceling) OrElse (activity.ExecutionStatus = ActivityExecutionStatus.Faulting)) OrElse ((activity.ExecutionStatus = ActivityExecutionStatus.Executing) AndAlso Not SequenceHelper.TryScheduleNextChild(activity, executionContext)))) Then
                activity.RemoveProperty(SequenceHelper.ActiveChildQualifiedNameProperty)
                executionContext.CloseActivity
            End If
            activity.RemoveProperty(SequenceHelper.ActiveChildRemovedProperty)
        End Sub

        Private Shared Function TryScheduleNextChild(ByVal activity As CompositeActivity, ByVal executionContext As ActivityExecutionContext) As Boolean
            Dim enabledActivities As IList([Of] Activity) = activity.EnabledActivities
            Dim num As Integer = 0
            Dim i As Integer = (enabledActivities.Count - 1)
            Do While (i >= 0)
                If (enabledActivities.Item(i).ExecutionStatus = ActivityExecutionStatus.Closed) Then
                    If (i = (enabledActivities.Count - 1)) Then
                        Return False
                    End If
                    num = (i + 1)
                    Exit Do
                End If
                i -= 1
            Loop
            enabledActivities.Item(num).RegisterForStatusChange(Activity.ClosedEvent, DirectCast(activity, IActivityEventListener([Of] ActivityExecutionStatusChangedEventArgs)))
            executionContext.ExecuteActivity(enabledActivities.Item(num))
            activity.SetValue(SequenceHelper.ActiveChildQualifiedNameProperty, enabledActivities.Item(num).QualifiedName)
            Return True
        End Function


        ' Fields
        Private Shared ActiveChildQualifiedNameProperty As DependencyProperty = DependencyProperty.RegisterAttached("ActiveChildQualifiedName", GetType(String), GetType(SequenceHelper))
        Private Shared ActiveChildRemovedProperty As DependencyProperty = DependencyProperty.RegisterAttached("ActiveChildRemoved", GetType(Boolean), GetType(SequenceHelper), New PropertyMetadata(DependencyPropertyOptions.NonSerialized))
    End Class
End Namespace

